package main

import (
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/sessions"
	"learn_login/model"
	"net/http"
	"os"
	"strconv"
)

var (
	store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))
)

const sessionID = "sessionID"

func init() {
	initDB()
}

func main() {
	r := gin.Default()
	r.LoadHTMLGlob("template/*")
	r.GET("/register", showRegisterPage)
	r.POST("/register", register)
	r.GET("/login", showLoginPage)
	r.POST("/login", login)
	r.GET("/home", info) // 首页

	err := r.Run(":81")
	if err != nil {
		panic(err)
	}
}

// 登录页面
func showLoginPage(c *gin.Context) {
	// 显示登录页面的时候，先判断浏览器的cookie是否已经记录了用户登录状态
	sid, err := c.Cookie(sessionID)
	if err == nil && sid != "" {
		// 跳转去首页
		c.Redirect(http.StatusFound, "/home")
	} else {
		// 显示登录页面
		c.HTML(http.StatusOK, "login.tmpl", nil)
	}
}

// 注册页面
func showRegisterPage(c *gin.Context) {
	// 显示注册页面的时候，先判断浏览器的cookie是否已经记录了用户登录状态
	sid, err := c.Cookie(sessionID)
	if err == nil && sid != "" {
		// 跳转去首页
		c.Redirect(http.StatusFound, "/home")
	} else {
		// 显示注册页面
		c.HTML(http.StatusOK, "register.tmpl", nil)
	}
}

func register(c *gin.Context) {
	u := &model.User{}
	u.Username = c.PostForm("username")
	u.Nickname = c.PostForm("nickname")
	u.Password = c.PostForm("password")
	// TODO 判断数据格式正确性
	// 写入数据库
	err := GetDB().Create(u).Error
	if err != nil {
		// 有错误需要根据实际业务处理，不能随意panic
		panic(err)
	}
	// 跳转去登录
	c.Redirect(http.StatusFound, "/login")
}

func info(c *gin.Context) {
	sid, err := c.Cookie(sessionID)
	if err != nil {
		// 跳转去登录
		c.Redirect(http.StatusFound, "/login")
	}

	// 从session读取用户信息
	session, err := store.Get(c.Request, sid)
	if err != nil {
		panic(err)
	}
	userId := session.Values["user_id"].(int64)

	var u model.User
	err = GetDB().Model(&model.User{}).
		Where(&model.User{
			ID: userId,
		}).
		First(&u).Error
	if err != nil {
		panic(err)
	}

	c.HTML(http.StatusOK, "home.tmpl", gin.H{
		"username": u.Username,
		"nickname": u.Nickname,
	})
}

func login(c *gin.Context) {
	req := &model.User{}
	req.Username = c.PostForm("username")
	req.Password = c.PostForm("password")
	// TODO 判断数据格式正确性
	// 去数据库查数据
	var u model.User
	err := GetDB().Model(&model.User{}).
		Where(&model.User{
			Username: req.Username,
		}).
		First(&u).Error
	if err != nil {
		// 同上
		panic(err)
	}
	// 实际情况下，密码需要处理过，这里demo用明文
	if u.Password != req.Password {
		// 同上
		panic(errors.New("密码错误"))
	}
	// 密码正确，写入session，这里session的name用了用户id，实际需要算法加密处理
	session, err := store.Get(c.Request, strconv.FormatInt(u.ID, 10))
	if err != nil {
		// 同上
		panic(err)
	}
	session.Values["user_id"] = u.ID
	err = session.Save(c.Request, c.Writer)
	if err != nil {
		// 同上
		panic(err)
	}
	// 用cookie记录sessionID，10秒过期
	c.SetCookie(sessionID, strconv.FormatInt(u.ID, 10), 10, "/", "localhost", false, true)
	// 返回提示
	c.Redirect(http.StatusFound, "/home")
}
